home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 July / macformat52.iso / mac / Shareware Plus / Developers / YAAF v1.0 alpha 1 / (Tools) / CompileVRes / lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-15  |  7.2 KB  |  416 lines

  1. /*    lex.c
  2.  *
  3.  *        This is the lexical engine
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <stdarg.h>
  11. #include "lex.h"
  12.  
  13. /************************************************************************/
  14. /*                                                                        */
  15. /*    Read Structures                                                        */
  16. /*                                                                        */
  17. /************************************************************************/
  18.  
  19. /*    ReadRecord
  20.  *
  21.  *        Record storing read/write data
  22.  */
  23.  
  24. struct ReadRecord {
  25.     char        file[64];
  26.     long        line;
  27.     int            push;
  28.     FILE        *fptr;
  29. };
  30.  
  31.  
  32. /************************************************************************/
  33. /*                                                                        */
  34. /*    Globals                                                                */
  35. /*                                                                        */
  36. /************************************************************************/
  37.  
  38. long                        GInteger;
  39. double                        GReal;
  40. char                        GToken[256];
  41.  
  42. static short                GPushToken;
  43. static int                    GReadPtr;
  44. static struct ReadRecord    GRead[8];
  45.  
  46. /************************************************************************/
  47. /*                                                                        */
  48. /*    Error management                                                    */
  49. /*                                                                        */
  50. /************************************************************************/
  51.  
  52. /*    PrintError
  53.  *
  54.  *        Print the error
  55.  */
  56.  
  57. void PrintError(char *arg,...)
  58. {
  59.     va_list vlist;
  60.     
  61.     va_start(vlist,arg);
  62.     if (GReadPtr >= 0) {
  63.         fprintf(stderr,"[%s@%ld] ",GRead[GReadPtr].file,GRead[GReadPtr].line);
  64.     }
  65.     vfprintf(stderr,arg,vlist);
  66.     fprintf(stderr,"\n");
  67.     va_end(vlist);
  68. }
  69.  
  70. /************************************************************************/
  71. /*                                                                        */
  72. /*    Token Search                                                        */
  73. /*                                                                        */
  74. /************************************************************************/
  75.  
  76. /*    TokenList
  77.  *
  78.  *        List of tokens
  79.  */
  80.  
  81. struct TokenElement {
  82.     int        value;
  83.     char    *token;
  84. } TokenList[] = {
  85.     {    KTokenDefine,    "define"    },
  86.     {    KTokenBool,        "bool"        },
  87.     {    KTokenString,    "string"    },
  88.     {    KTokenInteger,    "integer"    },
  89.     {    KTokenClass,    "class"        },
  90.     {    KTokenCreate,    "create"    },
  91.     {    KTokenTrue,        "true"        },
  92.     {    KTokenFalse,    "false"        },
  93.     {    KTokenView,        "view"        },
  94.     {    KTokenRead,        "read"        },
  95.     {    KTokenDimension,"dimension"    },
  96.     {    -1,                NULL        }
  97. };
  98.     
  99.  
  100. /*    TokenSearch
  101.  *
  102.  *        It ain't the quickest, but it works
  103.  */
  104.  
  105. static int TokenSearch(char *str)
  106. {
  107.     int i;
  108.     
  109.     for (i = 0; TokenList[i].token != NULL; i++) {
  110.         if (!strcmp(TokenList[i].token,str)) return TokenList[i].value;
  111.     }
  112.     return KLexToken;
  113. }
  114.  
  115.  
  116. /************************************************************************/
  117. /*                                                                        */
  118. /*    Lex Initialization                                                    */
  119. /*                                                                        */
  120. /************************************************************************/
  121.  
  122. /*    InitLexEngine
  123.  *
  124.  *        This handles initialization of the lexical engine
  125.  */
  126.  
  127. void InitLexEngine(void)
  128. {
  129.     GReadPtr = -1;
  130.     GPushToken = -1;
  131. }
  132.  
  133. /*    EndLexEngine
  134.  *
  135.  *        End the lexical parser
  136.  */
  137.  
  138. void EndLexEngine(void)
  139. {
  140.     while (GReadPtr >= 0) fclose(GRead[GReadPtr--].fptr);
  141.     GPushToken = -1;
  142. }
  143.  
  144. /*    ReadLexFile
  145.  *
  146.  *        Read a file
  147.  */
  148.  
  149. void ReadLexFile(char *f)
  150. {
  151.     FILE *fptr;
  152.     
  153.     if (GReadPtr >= 7) PrintError("Can't open '%s': too many open files",f);
  154.     fptr = fopen(f,"r");
  155.     if (fptr == NULL) PrintError("Can't open '%s': unable to find file",f);
  156.  
  157.     GReadPtr++;
  158.     strcpy(GRead[GReadPtr].file,f);
  159.     GRead[GReadPtr].line = 1;
  160.     GRead[GReadPtr].fptr = fptr;
  161.     GRead[GReadPtr].push = -1;
  162. }
  163.  
  164. /************************************************************************/
  165. /*                                                                        */
  166. /*    Low level char reader                                                */
  167. /*                                                                        */
  168. /************************************************************************/
  169.  
  170. /*    ReadChar
  171.  *
  172.  *        Read a character--this strips out C and C++ style comments
  173.  */
  174.  
  175. static int ReadChar(void)
  176. {
  177.     int c;
  178.     int d;
  179.     
  180.     /*
  181.      *    Simple screening
  182.      */
  183.     
  184.     if (GReadPtr < 0) return -1;
  185.     if (GRead[GReadPtr].push != -1) {
  186.         c = GRead[GReadPtr].push;
  187.         GRead[GReadPtr].push = -1;
  188.         return c;
  189.     }
  190.  
  191.     /*
  192.      *    Pop files that are at EOL
  193.      */
  194.     
  195.     c = fgetc(GRead[GReadPtr].fptr);
  196.     if (c == -1) {
  197.         fclose(GRead[GReadPtr--].fptr);
  198.         return ' ';
  199.     }
  200.     
  201.     /*
  202.      *    Update line count
  203.      */
  204.     
  205.     if (c == '\n') GRead[GReadPtr].line++;
  206.  
  207.     /*
  208.      *    Strip comments
  209.      */
  210.     
  211.     if (c == '/') {
  212.         d = fgetc(GRead[GReadPtr].fptr);
  213.         if (d == '/') {
  214.             /*
  215.              *    Scan for C++ style comment
  216.              */
  217.             
  218.             while ((d != -1) && (d != '\n')) {
  219.                 d = fgetc(GRead[GReadPtr].fptr);
  220.             }
  221.             GRead[GReadPtr].line++;
  222.             return '\n';
  223.         }
  224.         
  225.         if (d == '*') {
  226.             /*
  227.              *    Scan for C style comment
  228.              */
  229.             
  230.             for (;;) {
  231.                 c = fgetc(GRead[GReadPtr].fptr);
  232.                 if (c == '\n') {
  233.                     GRead[GReadPtr].line++;
  234.                 }
  235.                 if (c == -1) {
  236.                     PrintError("End of comment reached in file");
  237.                     GRead[GReadPtr].line++;
  238.                     return ' ';
  239.                 }
  240.                 if (c == '*') {
  241.                     c = fgetc(GRead[GReadPtr].fptr);
  242.                     if (c == '/') return ' ';
  243.                     ungetc(c,GRead[GReadPtr].fptr);
  244.                 }
  245.             }
  246.         }
  247.         
  248.         /*
  249.          *    Not a comment
  250.          */
  251.         
  252.         ungetc(d,GRead[GReadPtr].fptr);
  253.     }
  254.     return c;
  255. }
  256.  
  257. /*    PushChar
  258.  *
  259.  *        Push character back; store on the GPushChar variable because
  260.  *    we're using the available slot in the ungetc for pushing comments
  261.  */
  262.  
  263. static void PushChar(int c)
  264. {
  265.     if (GReadPtr >= 0) GRead[GReadPtr].push = c;
  266. }
  267.  
  268. /************************************************************************/
  269. /*                                                                        */
  270. /*    High level token reader                                                */
  271. /*                                                                        */
  272. /************************************************************************/
  273.  
  274. /*    PushBackToken
  275.  *
  276.  *        Push token back
  277.  */
  278.  
  279. void PushBackToken(int c)
  280. {
  281.     GPushToken = c;
  282. }
  283.  
  284. /*    GetNextToken
  285.  *
  286.  *        Get the next token
  287.  */
  288.  
  289. int GetNextToken(void)
  290. {
  291.     int c;
  292.     int d;
  293.     
  294.     /*
  295.      *    Get pushed tokens
  296.      */
  297.     
  298.     if (GPushToken != -1) {
  299.         c = GPushToken;
  300.         GPushToken = -1;
  301.         return c;
  302.     }
  303.  
  304.     /*
  305.      *    Get the token
  306.      */
  307.     
  308.     do {
  309.         c = ReadChar();
  310.     } while (isspace(c));
  311.     
  312.     /*
  313.      *    What type of character do I have?
  314.      */
  315.      
  316.     if (c == '"') {
  317.         /*
  318.          *    Read rest of string (don't use ReadChar--get comments too)
  319.          */
  320.         
  321.         d = 0;
  322.         c = fgetc(GRead[GReadPtr].fptr);
  323.         while ((c != '"') && (c != '\n') && (c != -1)) {
  324.             GToken[d++] = c;
  325.             if (d >= 255) break;
  326.             c = fgetc(GRead[GReadPtr].fptr);
  327.         }
  328.         
  329.         /*
  330.          *    Return type
  331.          */
  332.         
  333.         GToken[d] = 0;
  334.         return KLexString;
  335.     }
  336.     
  337.     if ((c == '$') || (c == '_') || isalpha(c)) {
  338.         /*
  339.          *    Read rest of token
  340.          */
  341.         
  342.         d = 0;
  343.         while ((c == '$') || (c == '_') || isalnum(c)) {
  344.             GToken[d++] = c;
  345.             if (d >= 255) break;
  346.             c = ReadChar();
  347.         }
  348.         PushChar(c);
  349.         
  350.         /*
  351.          *    Null terminate token and return
  352.          */
  353.         
  354.         GToken[d] = 0;
  355.         return TokenSearch(GToken);
  356.     }
  357.     
  358.     if ((c == '-') || (c == '.') || isdigit(c)) {
  359.         /*
  360.          *    Look forward if '-' or '.' for number component
  361.          */
  362.         
  363.         if (c == '-') {
  364.             d = ReadChar();                /* Quick readahead */
  365.             PushChar(d);
  366.             if ((d != '.') && !isdigit(d)) {
  367.                 GToken[0] = '-';
  368.                 GToken[1] = 0;
  369.                 return '-';
  370.             }
  371.         } else if (c == '.') {
  372.             d = ReadChar();
  373.             PushChar(d);
  374.             if (!isdigit(d)) {
  375.                 GToken[0] = '.';
  376.                 GToken[1] = 0;
  377.                 return '.';
  378.             }
  379.         }
  380.         
  381.         /*
  382.          *    Read the rest of the number
  383.          */
  384.         
  385.         d = 0;
  386.         do {
  387.             GToken[d++] = c;
  388.             if (d >= 255) break;
  389.             c = ReadChar();
  390.         } while ((c == '.') || isdigit(c));
  391.         PushChar(c);
  392.         
  393.         /*
  394.          *    Conversion
  395.          */
  396.         
  397.         GToken[d] = 0;
  398.         for (c = 0; GToken[c]; c++) {
  399.             if (GToken[c] == '.') break;
  400.         }
  401.         GInteger = atol(GToken);
  402.         GReal    = atof(GToken);
  403.         if (GToken[c]) return KLexReal;
  404.         else return KLexInteger;
  405.     }
  406.     
  407.     /*
  408.      *    If we get here, we have a simple token.
  409.      */
  410.     
  411.     GToken[0] = c;
  412.     GToken[1] = 0;
  413.     return c;
  414. }
  415.  
  416.